#include "typedef.h"
#include "astraldef.h"
#include "_2arch.h"
#include "arm_common.h"

executable arch_exe_ttimer;
executable arch_exe_tsched;
executable arch_irq_handler;
int irqcounts[CFG_CORE_NUM];

word arch_disable_local_irq()
{
    word status = 0;
    asm volatile(" mrs     %0, cpsr\n\t"
                 "cpsid if\n\t" : "=r"(status) :);
    status = status & (0x80|0x40);
    return status;
}

void arch_enable_local_irq(word status)
{
    switch (status & (0x80|0x40))
    {
    case 0x40:
        // fiq disabled
        asm volatile("cpsie i");
        break;
    case 0x80:
        // irq disabled
        asm volatile("cpsie f");
        break;
    case 0x0:
        asm volatile("cpsie if");
    default:
        break;
    }
}

/**
 * @brief This function is called by irq_handler
 * 
 * @param id the interrupt id
 */
void do_irq_handle(int id, int core)
{
    irqcounts[core]++;

    switch (id)
    {
    case 29:
        // gic_send_ici(0, 0x0, 0b01); // send all except self
        if(arch_exe_ttimer)
        {
            if(core == 0)
            {
                arch_exe_ttimer(NULL);
            }
        }
        if (arch_exe_tsched)
        {
            arch_exe_tsched(NULL);
        }
        clean_private_timer_int_status();
        break;
    default:
        if (arch_irq_handler)
        {
            arch_irq_handler(CAST_AS(object, id));
        }
        break;
    }
}

typedef struct StackFrame
{
    u32 magic;
    u32 cpsr;
    u32 r0;
    u32 r1;
    u32 r2;
    u32 r3;
    u32 r4;
    u32 r5;
    u32 r6;
    u32 r7;
    u32 r8;
    u32 r9;
    u32 r10;
    u32 r11;
    u32 r12;
    u32 lr;
} *StackFrame;


void other_exception_handle(int type, StackFrame frame, int core)
{
    switch (type)
    {
    case 1:
        kerror("unable to handle exception %s\n", "reset");
        break;
    case 2:
        kerror("unable to handle exception %s\n", "undef");
        break;
    case 3:
        kerror("unable to handle exception %s\n", "svc");
        break;
    case 4:
        kerror("unable to handle exception %s\n", "prefetch");
        break;
    case 5:
        kerror("unable to handle exception %s\n", "data");
        break;
    case 6:
        kerror("unable to handle exception %s\n", "fiq");
        break;

    default:
        kerror("unable to handle exception %s\n", "??");
        break;
    }
    kprint("Coredump on core %d:\n", core);
    kprint(" r00: %x\n", frame->r0);
    kprint(" r01: %x\n", frame->r1);
    kprint(" r02: %x\n", frame->r2);
    kprint(" r03: %x\n", frame->r3);
    kprint(" r04: %x\n", frame->r4);
    kprint(" r05: %x\n", frame->r5);
    kprint(" r06: %x\n", frame->r6);
    kprint(" r07: %x\n", frame->r7);
    kprint(" r08: %x\n", frame->r8);
    kprint(" r09: %x\n", frame->r9);
    kprint(" r10: %x\n", frame->r10);
    kprint(" r11: %x\n", frame->r11);
    kprint(" r12: %x\n", frame->r12);
    kprint("  lr: %x\n", frame->lr);
    kprint("cpsr: %x\n", frame->cpsr);
    kprint("iden: %x\n", frame->magic);
    while(1)
    {
    }
}